import { getRequestIP } from "h3"; import { getPublicPostCommentContext } from "#server/service/posts"; import { createComment } from "#server/service/post-comments"; import { assertUnderRateLimit } from "#server/utils/simple-rate-limit"; export default defineEventHandler(async (event) => { const publicSlug = event.context.params?.publicSlug; const postSlug = event.context.params?.postSlug; if (!publicSlug || !postSlug || typeof publicSlug !== "string" || typeof postSlug !== "string") { throw createError({ statusCode: 400, statusMessage: "无效请求" }); } const ctx = await getPublicPostCommentContext(publicSlug, postSlug); if (!ctx) { throw createError({ statusCode: 404, statusMessage: "未找到" }); } const viewer = await event.context.auth.getCurrent(); const ip = getRequestIP(event, { xForwardedFor: true }) ?? "unknown"; if (viewer == null) { assertUnderRateLimit(`comment-post-guest:${ip}`, 20, 15 * 60 * 1000); } else { assertUnderRateLimit(`comment-post-user:${viewer.id}`, 60, 15 * 60 * 1000); } const body = await readBody<{ parentId?: number | null; guestDisplayName?: string; body: unknown; }>(event); if (typeof body.body !== "string") { throw createError({ statusCode: 400, statusMessage: "无效请求" }); } let parentId: number | null; if (body.parentId === undefined || body.parentId === null) { parentId = null; } else if (typeof body.parentId === "number" && Number.isFinite(body.parentId)) { parentId = body.parentId; } else { throw createError({ statusCode: 400, statusMessage: "无效请求" }); } const newCommentId = await createComment({ postId: ctx.id, ownerUserId: ctx.userId, parentId, viewer, guestDisplayName: typeof body.guestDisplayName === "string" ? body.guestDisplayName : undefined, body: body.body, }); return R.success({ id: newCommentId }); });